package com.kvn.mock.local;

import com.alibaba.fastjson.JSON;
import com.kvn.mock.local.processor.MockProcessor;
import com.kvn.mock.local.processor.MockProcessorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * mock 代理。需要能代理具体类或接口，选用 cglib
 * Created by wangzhiyuan on 2018/11/6
 */
public class MockProxy implements MethodInterceptor {
    private static final Logger log = LoggerFactory.getLogger(MockProxy.class);

    private Object target;
    private MockProcessorFactory mockProcessorFactory;

    public MockProxy(Object target, MockProcessorFactory mockProcessorFactory) {
        this.target = target;
        this.mockProcessorFactory = mockProcessorFactory;
    }

    /**
     * 获取代理对象
     * @return
     */
    public Object getProxy(){
        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(target.getClass().getClassLoader());
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }


    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        if (!MockConfig.openMock) {
            log.info("mock开关关闭，不开启mock.....");
            return method.invoke(target, args);
        }

        MockProcessor matchedProcessor = mockProcessorFactory.getMatchedProcessor(method, null);
        // 如果没有配置 mock，就调用原始方法
        if (matchedProcessor == null) {
            return method.invoke(target, args);
        }
        log.info("mock开启.....被mock的方法-->{}, needCache-->{}", method.getDeclaringClass() + "#" + method.getName(), MockConfig.needCache);
        Object response = matchedProcessor.process(MockConfig.getMockItem(method), method.getReturnType(), method, args);
        log.info("mock的返回结果 ===> {}", JSON.toJSONString(response));
        return response;
    }
}
